﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Utils
{
   public class Encryption
    {
        private int intPrivateKey = 0;
        private static long MaxInt = (long)Math.Pow(2.0D, 32.0D);

        private int[] intConstKey = { 1556696929, 1266038903, 1265722019, 1265722531, 
    1265658509, 1265282947, 1263528397, 1263599759, 
    1263487033, 1263648241, 1262235517, 1262210177, 
    1261371079, 1261525493, 1261118363, 1260675071, 
    1260706169, 1260299731, 1260230359, 1259026997, 
    1258887283, 1258865891, 1258626371, 1258503781, 
    1258482227, 1258579643, 1258190971, 1258098757, 
    1257611279, 1257724121, 1257273319, 1257361279, 
    1256913187, 1256892151, 1256455111, 1256408429, 
    1060988843, 1028046497, 1059548141, 1059702103, 
    1059282011, 1057910353, 1057261279, 1056410731, 
    1027302959, 1056241757, 1053532217, 1053109769, 
    1052145631, 1052156549, 1052311109, 1052138359, 
    1051307749, 1051455023, 1030905121, 1030546703, 
    1030613851, 1030517641, 1029296581, 1029412469, 
    1028968387, 1028847733, 1028118731, 1028044769 };

        private int[] intUserKey = new int[64];

        private int[] intPosition = new int[64];

        private static int encryptionInfo = 3;

       
        public static long lngREMAINTIMER = 600000L;
        public static long abc = long.Parse("7776000000");

        public Encryption(String strKey)
        {
            int[] intData = getStringLong(strKey);
            this.intPrivateKey = 0;
            if (intData != null)
            {
                for (int i = 0; i < intData.Length; i++)
                {
                    this.intPrivateKey ^= intData[i];
                }
            }
            intData = getStringLong(this.intPrivateKey.ToString());
            for (int i = 0; i < intData.Length; i++)
            {
                this.intPrivateKey ^= intData[i];
            }
            processKeyGene();
        }

        public Encryption()
        {
        }

        public int[] getStringLong(string strString)
        {
            ushort strByte = byte.Parse(strString);
            byte[] byteString = BitConverter.GetBytes(strByte);
            int intI = 0;
            int intIndex = -1;

            int intByte = 0;
            if (byteString.Length == 0)
            {
                return null;
            }
            int[] intData = new int[(byteString.Length - 1) / 4 + 1];
            while (intI < byteString.Length)
            {
                if (intI % 4 == 0)
                {
                    intData[(++intIndex)] = 0;
                }
                intByte = byteString[(intI++)];
                if (intByte < 0)
                {
                    intByte += 256;
                }
                intData[intIndex] = ((intData[intIndex] << 8) + intByte);
            }
            return intData;
        }

        public String getLongString(int[] intData)
        {
            String strData = "";
            if (intData != null)
            {
                int[] intLocation = { -16777216, 16711680, 65280, 255 };
                int[] intMove = { 24, 16, 8 };
                int intIndex = 0; int intI = 0;
                int intLen = (intData.Length - 1) * 4 + 1;
                int tmp = intData[(intData.Length - 1)];
                if (tmp < 0)
                    intLen += 3;
                else
                {
                    while (tmp > 255)
                    {
                        intLen++;
                        tmp >>= 8;
                    }
                }
                byte[] bytString = new byte[intLen];
                intLen = 0;
                while (intI < intData.Length - 1)
                {
                    bytString[(intLen++)] = ((byte)((intData[intI] & intLocation[intIndex]) >> intMove[intIndex]));
                    intIndex++; if (intIndex > 3)
                    {
                        intI++;
                        intIndex = 0;
                    }
                }
                tmp = intData[(intData.Length - 1)];
                for (intI = bytString.Length - 1; intI >= intLen; intI--)
                {
                    bytString[intI] = ((byte)(tmp & 0xFF));
                    tmp >>= 8;
                }
                strData = bytString.ToString();
            }
            return strData;
        }

        public int[] getHexLong(string strHex)
        {
            if (strHex.Length == 0)
            {
                return null;
            }
            int[] intData = new int[(strHex.Length - 1) / 8 + 1];
            String strSubHex = "";
            for (int i = 0; i < strHex.Length; i += 8)
            {
                if (i + 8 < strHex.Length)
                    strSubHex = strHex.Substring(i, i + 8);
                else
                {
                    strSubHex = strHex.Substring(i);
                }

                intData[(i / 8)] = Int32.Parse(String.Format("{0:x}", strSubHex), System.Globalization.NumberStyles.HexNumber);
            }
            return intData;
        }

        public String getLongHex(int[] intData)
        {
            String strHex = "";
            String strSubHex = "";
            if (intData != null)
            {
                for (int i = 0; i < intData.Length - 1; i++)
                {
                    strSubHex = String.Format("{0:x}", intData[i]).ToUpper();
                    for (int j = strSubHex.Length; j < 8; j++)
                    {
                        strSubHex = "0" + strSubHex;
                    }
                    strHex = strHex + strSubHex;
                }
                strSubHex = String.Format("{0:x}", intData[(intData.Length - 1)]).ToUpper();
                if (strSubHex.Length % 2 != 0)
                {
                    strSubHex = "0" + strSubHex;
                }
                strHex = strHex + strSubHex;
            }
            return strHex;
        }

        private void processKeyGene()
        {
            bool[] blnInGene = new bool[64];
            int intG = 0; int intGCount = -1; int intCount = 0;
            int[] intGene = new int[64];
            string strPrivateKey = this.intPrivateKey.ToString();
            for (int i = 0; i < 64; i++)
            {
                this.intUserKey[i] = this.intConstKey[i];
                blnInGene[i] = false;
                this.intPosition[i] = i;
                intGene[i] = -1;
            }
            for (int i = 0; i < strPrivateKey.Length; i++)
            {
                if (strPrivateKey.Substring(i, i + 1)=="-")
                    intG = 0;
                else
                {
                    intG = int.Parse(strPrivateKey.Substring(i, i + 1));
                }
                if (blnInGene[intG] == false)
                {
                    blnInGene[intG] = true;
                    this.intPrivateKey = (this.intUserKey[intG] ^ this.intPrivateKey);
                    intGCount++;
                    intGene[intGCount] = intG;
                }
            }
            intCount = intGCount;
            for (int i = 0; i <= intCount; i++)
            {
                if ((intGene[i] > 0) && (intGene[i] < 7))
                {
                    for (int j = 0; j <= intCount; j++)
                    {
                        intG = intGene[i] * 10 + intGene[j];
                        if ((intG < 64) && (blnInGene[intG] == false))
                        {
                            intGCount++;
                            intGene[intGCount] = intG;
                            this.intPrivateKey = (this.intUserKey[intG] ^ this.intPrivateKey);
                        }
                    }
                }
            }
            intGCount++;
            for (int i = 0; i < 64; i++)
            {
                int j = (int)(intGene[(i % intGCount)] * Math.Pow(i, 2.0D)) & 0x1F;
                intG = this.intUserKey[i];
                this.intUserKey[i] = this.intUserKey[j];
                this.intUserKey[j] = intG;
                intG = this.intPosition[i];
                this.intPosition[i] = this.intPosition[j];
                this.intPosition[j] = intG;
            }
        }

        public String encryptString(String strString, bool blnGetHex)
        {
            if (EncrypUtil.isFingerprint(strString))
            {
                return EncrypUtil.getFingerValue(strString);
            }
            if (blnGetHex)
            {
                return getLongHex(encryptData(getStringLong(strString), true));
            }
            return getLongString(encryptData(getStringLong(strString), true));
        }

        public String encryptString(String strString)
        {
            return getLongString(encryptData(getStringLong(strString), true));
        }

        public String decryptionString(String strString, bool blnIsHex)
        {
            if (blnIsHex)
            {
                return getLongString(encryptData(getHexLong(strString), false));
            }
            return getLongString(encryptData(getStringLong(strString), false));
        }

        public String decryptionString(String strString)
        {
            return getLongString(encryptData(getStringLong(strString), false));
        }

        public int[] encryptData(int[] intData, bool blnEncryption)
        {
            if (intData == null)
            {
                return null;
            }
            int intLen = intData.Length;
            int[] intEncryptData = new int[intLen];
            int[] intModPosition = (int[])null;
            int intMod = intLen & 0x3F;
            if (intMod > 0)
            {
                intModPosition = new int[intMod];
                int index = -1;
                for (int i = 0; i < 64; i++)
                {
                    if (this.intPosition[i] < intMod)
                    {
                        intModPosition[(++index)] = this.intPosition[i];
                    }
                }
            }
            if (blnEncryption)
            {
                for (int i = 0; i < intLen; i++)
                    if (intLen - i > 63)
                    {
                        for (int j = 0; j < 64; j++)
                        {
                            intEncryptData[(i + j)] = (intData[(i + this.intPosition[j])] ^ this.intPrivateKey ^ this.intUserKey[j]);
                        }
                        i += 63;
                    }
                    else
                    {
                        for (int j = 0; j < intLen - i; j++)
                        {
                            intEncryptData[(i + j)] = (intData[(i + intModPosition[j])] ^ this.intPrivateKey ^ this.intUserKey[j]);
                        }
                        i = intLen;
                    }
            }
            else
            {
                for (int i = 0; i < intData.Length; i++)
                {
                    if (intLen - i > 63)
                    {
                        for (int j = 0; j < 64; j++)
                        {
                            intEncryptData[(i + this.intPosition[j])] = (intData[(i + j)] ^ this.intPrivateKey ^ this.intUserKey[j]);
                        }
                        i += 63;
                    }
                    else
                    {
                        for (int j = 0; j < intLen - i; j++)
                        {
                            intEncryptData[(i + intModPosition[j])] = (intData[(i + j)] ^ this.intPrivateKey ^ this.intUserKey[j]);
                        }
                        i = intLen;
                    }
                }
            }
            return intEncryptData;
        }

        public static int getEncryptionMachineInfo()
        {
            return encryptionInfo;
        }

       
    }
}
